package com.xvyy.tingshu.album.service.impl;



import com.xvyy.tingshu.album.service.VodService;
import com.xvyy.tingshu.common.minio.config.MinioProperties;
import com.xvyy.tingshu.common.execption.TsException;

import com.xvyy.tingshu.album.service.FileUploadService;
import com.xvyy.tingshu.common.util.MD5;

import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.StatObjectArgs;
import io.minio.errors.MinioException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * ClassName: FileUploadServiceImpl
 * Package: com.xvyy.tingshu.album.service.impl
 *
 * @Description:
 * @Author: xvyy
 * @Create: 2025/1/14 - 18:26
 * @Version: v1.0
 */
@Service
@Slf4j
public class FileUploadServiceImpl implements FileUploadService {

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private VodService vodService;

    @Override
    public String fileUpload(MultipartFile file) {

        String picUrl = "";
        String originalFilename = file.getOriginalFilename();// 获取原始文件名
        String bucketName = minioProperties.getBucketName();// 获取bucket名称
        String endpointUrl = minioProperties.getEndpointUrl();

        try {
            // 1. 文件名拼接
            // 1.1 获取文件字节数组
            byte[] bytes = file.getBytes();
            // 1.2 字节数组转字符串 (utf-8)
            String fileContentStr = new String(bytes, StandardCharsets.UTF_8);
            // 1.3 MD5算法加密 文件前缀
            String filePrefix = MD5.encrypt(fileContentStr);
            // 1.4 文件后缀 通过原始文件名.substring获取
            String fileSuffix = originalFilename.substring(file.getOriginalFilename().lastIndexOf("."), originalFilename.length());
            // 1.5 文件名拼接
            String objectName = filePrefix + fileSuffix;

            // 2. 去重校验
            StatObjectArgs.Builder statObjectArgsBuilder = StatObjectArgs.builder();
            StatObjectArgs statObjectArgs = statObjectArgsBuilder
                    .bucket(bucketName)
                    .object(objectName)
                    .build();

            picUrl = endpointUrl + "/" + bucketName + "/" + objectName;
            try {
                // 校验是否存在同名文件
                // 如果不抛出异常，则代表minio指定桶中的文件已经存在，反之对象不存在
                minioClient.statObject(statObjectArgs);
                log.info("文件已存在，直接返回原有链接");
                return picUrl;
            } catch (MinioException e) {//ErrorResponseException 继承自RuntimeException
                // 3. 上传文件
                // 3.1 构建一个PutObjectArgs对象
                PutObjectArgs.Builder builder = PutObjectArgs.builder();
                PutObjectArgs putObjectArgs = builder
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .build();
                // 3.2 上传文件
                minioClient.putObject(putObjectArgs);
                log.info("文件上传成功");
                // 4. 返回文件访问链接
                return picUrl;
            }
        } catch (Exception e) {
            log.error("文件上传失败: {}", e.getMessage());
            throw new TsException(201, "文件上传失败");
        }
    }

    @Override
    public Map<String, Object> uploadTrack(MultipartFile file) {
        return vodService.uploadTrack(file);
    }

}

